package com.biz.primus.ms.order.service.helper;

import com.biz.primus.base.enums.PromotionTypeEnum;
import com.biz.primus.base.exception.BizSilentException;
import com.biz.primus.base.exception.utils.AssertUtils;
import com.biz.primus.common.enums.StockChannelEnum;
import com.biz.primus.common.utils.CopyUtils;
import com.biz.primus.common.utils.DateUtil;
import com.biz.primus.model.depot.vo.DepotDeliverPriceRespVo;
import com.biz.primus.model.depot.vo.DepotRespVo;
import com.biz.primus.model.order.enums.*;
import com.biz.primus.model.order.exception.OrderException;
import com.biz.primus.model.order.exception.utils.AssertRequestParameter;
import com.biz.primus.model.order.vo.request.OrderItemRequestVO;
import com.biz.primus.model.order.vo.request.OrderRequestVO;
import com.biz.primus.model.order.vo.request.OrderSummaryRequestVO;
import com.biz.primus.model.order.vo.request.PaidOrderRequestVO;
import com.biz.primus.model.order.vo.response.OrderResponseVO;
import com.biz.primus.model.promotion.vo.req.OrderPromotionReqDetailVo;
import com.biz.primus.model.promotion.vo.req.OrderPromotionReqVo;
import com.biz.primus.model.promotion.vo.req.TakeMemberPromotionReqVo;
import com.biz.primus.model.promotion.vo.resp.OrderPromotionRespVo;
import com.biz.primus.model.stock.enums.StockChangeTypeEnum;
import com.biz.primus.model.stock.vo.IncrDepotStockReqVo;
import com.biz.primus.model.stock.vo.ProductQuantityPair;
import com.biz.primus.ms.base.service.AbstractBaseService;
import com.biz.primus.ms.order.convertor.OrderConvertor;
import com.biz.primus.ms.order.convertor.OrderItemConvertor;
import com.biz.primus.ms.order.dao.po.*;
import com.biz.primus.ms.order.dao.repository.*;
import com.biz.primus.ms.order.dao.specfication.OrderSpecfication;
import com.biz.primus.ms.order.feign.*;
import com.biz.primus.ms.order.paymentway.service.PaymentWayService;
import com.biz.primus.product.vo.OrderProductInfoRespVo;
import com.biz.primus.product.vo.OrderProductReqVo;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.codelogger.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单服务助手，为构建器和业务类提供数据
 *
 * @author Tiger Feng
 * @date 2017年10月31日
 */
@Slf4j
@Service
public class OrderServiceHelper extends AbstractBaseService {
    @Autowired
    private DepotFeignClient depotService;
    @Autowired
    private StockFeignClient stockService;
    @Autowired
    private PromotionFeignClient promotionService;
    @Autowired
    private ProductFeignClient productService;
    @Autowired
    private DepotDeliverPriceFeignClient depotDeliverPriceService;
    //=========================================
    @Autowired
    private PaymentWayService paymentWayService;
    @Autowired
    private OrderSummaryRepository orderSummaryRepository;
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private OrderItemRepository orderItemRepository;

    @Autowired
    private ReturnOrderRepository returnOrderRepository;
    @Autowired
    private ReturnOrderItemRepository returnOrderItemRepository;

    /**
     * 物流免费额度
     */
    private final Integer FREE_DELIVERY_MONEY = 99;

    /**
     * 根据门店编码获取门店信息
     *
     * @param depotCode
     * @return
     */
    public DepotRespVo getDepotByCode(String depotCode) {
        Optional<DepotRespVo> depotRespVoOption = depotService.queryByDepotCode(depotCode);
        if (depotRespVoOption.isPresent()) {
            return depotRespVoOption.get();
        } else {
            return null;
        }
    }

    /**
     * 获取可支付方式列表
     *
     * @return
     */
    public List<OrderPaymentWay> findSupportWays() {
        return paymentWayService.findSupportWays();
    }

    public boolean isFreeDelivery(Integer money) {
        return FREE_DELIVERY_MONEY <= money;
    }

    /**
     * 保存订单汇总
     */
    public OrderSummary saveOrderSummary(OrderSummary orderSummary) {
        if (orderSummary == null) {
            throw new BizSilentException(OrderException.ORDER_EXCEPTION);
        }
        if (orderSummary.getStoreOrder() != null) {
            orderSummary.getStoreOrder().setId(idService.getNextId());
            if (orderSummary.getStoreOrder().getItems() != null) {
                for (OrderItem item : orderSummary.getStoreOrder().getItems()) {
                    item.setId(idService.getNextId());
                    item.setOrder(orderSummary.getStoreOrder());
                }
            }
        }
        if (orderSummary.getFlagshipOrder() != null) {
            orderSummary.getFlagshipOrder().setId(idService.getNextId());
            if (orderSummary.getFlagshipOrder().getItems() != null) {
                for (OrderItem item : orderSummary.getFlagshipOrder().getItems()) {
                    item.setId(idService.getNextId());
                    item.setOrder(orderSummary.getFlagshipOrder());
                }
            }
        }
        orderSummary.setId(idService.getNextId());
        return orderSummaryRepository.save(orderSummary);
    }

    /**
     * 获取订单信息
     *
     * @param orderCode 订单编码
     * @return
     */
    public Order getByOrderCode(String orderCode) {
        AssertUtils.hasLength(orderCode, OrderException.ORDER_CODE_CANNOT_NULL);
        return orderRepository.findByOrderCode(orderCode);
    }


    public List<OrderResponseVO> getByOrderCodeAndState(String orderCode, OrderState orderState) {
        List<Order> orders = orderRepository.findAll(new OrderSpecfication(orderCode, orderState));

        return Optional.of(orders).orElse(new ArrayList<>()).stream().map(vo -> {
            OrderResponseVO orderResponseVO = new OrderResponseVO();
            CopyUtils.copyNotNullProperies(vo, orderResponseVO);
            return orderResponseVO;
        }).collect(Collectors.toList());
    }

    /**
     * 订单支付成功后修改订单状态
     *
     * @param paidOrderRequestVO
     */
    public OrderSummary updateOrderSummary2Paid(PaidOrderRequestVO paidOrderRequestVO) {
        AssertRequestParameter.notNull(paidOrderRequestVO, "请求参数不能为空");
        AssertRequestParameter.notNull(paidOrderRequestVO.getPaidAmount(), "支付金额不能为空");
        AssertRequestParameter.notNull(paidOrderRequestVO.getOrderSummaryCode(), "订单汇总编号不能为空");
        AssertRequestParameter.notNull(paidOrderRequestVO.getPaidSerialNumber(), "支付流水号不能为空");
        OrderSummary orderSummary = orderSummaryRepository.findByOrderSummaryCode(paidOrderRequestVO.getOrderSummaryCode());
        AssertUtils.notNull(orderSummary, OrderException.ORDER_NOT_EXIST);
        // 校验实际支付金额是否与订单金额相等,不能抛出异常，记录日志
        /*AssertUtils.isTrue(
                paidOrderRequestVO.getPaidAmount().intValue() == orderSummary.getPayableAmount(),
                OrderException.PAID_AMOUNT_INCONFORMITY);*/
        Timestamp paidTimestamp = paidOrderRequestVO == null ?
                new Timestamp(System.currentTimeMillis()) :
                paidOrderRequestVO.getPaiTimestamp();
        // 门店订单
        Order storeOrder = orderSummary.getStoreOrder();
        if (storeOrder != null) {
            storeOrder.setPaymentTimestamp(paidTimestamp);
            // 支付状态 -> 支付成功
            storeOrder.setPaymentState(PaymentState.PAY_SUCCESS);
            // 订单状态 -> 待发货
            storeOrder.setState(OrderState.WAIT_SEND);
        }
        // 总店订单
        Order flagshipOrder = orderSummary.getFlagshipOrder();
        if (flagshipOrder != null) {
            flagshipOrder.setPaymentTimestamp(paidTimestamp);
            // 支付状态 -> 支付成功
            flagshipOrder.setPaymentState(PaymentState.PAY_SUCCESS);
            // 订单状态 -> 待发货
            flagshipOrder.setState(OrderState.WAIT_SEND);
        }
        // 订单汇总状态信息
        orderSummary.setPaymentState(PaymentState.PAY_SUCCESS);
        // 支付时间
        orderSummary.setPaymentTimestamp(paidTimestamp);
        // 支付金额
        orderSummary.setPaidAmount(paidOrderRequestVO.getPaidAmount());
        // 支付流水号
        orderSummary.setPaidSerialNumber(paidOrderRequestVO.getPaidSerialNumber());
        // 修改数据库记录
        return orderSummaryRepository.save(orderSummary);
    }

    /**
     * 减库存锁定
     *
     * @param order
     */
    public void subtractLockStock(Order order) {
        // 订单为空或者不是门店订单都不处理
        if (order == null || !order.isStoreOrder()) {
            return;
        }
        List<ProductQuantityPair> items = order.getItems()
                .stream()
                .filter(orderItem -> orderItem.getQuantity() > 0)
                .map(orderItem -> new ProductQuantityPair(orderItem.getProductCode(), -orderItem.getQuantity()))
                .collect(Collectors.toList());

        IncrDepotStockReqVo incrDepotStockReqVo = new IncrDepotStockReqVo(
                items,
                order.getOrderCode(),
                order.getDepotCode(),
                StockChangeTypeEnum.SALE,
                StockChannelEnum.NORMAL);
        stockService.updateLockedStockOnly(incrDepotStockReqVo);
    }

    /**
     * 增加库存锁定,分布式回滚接口
     *
     * @param order
     */
    public void addLockStock(Order order) {
        // 订单为空或者不是门店订单都不处理
        if (order == null || !order.isStoreOrder()) {
            return;
        }
        List<ProductQuantityPair> items = order.getItems()
                .stream()
                .filter(orderItem -> orderItem.getQuantity() > 0)
                .map(orderItem -> new ProductQuantityPair(orderItem.getProductCode(), orderItem.getQuantity()))
                .collect(Collectors.toList());
        IncrDepotStockReqVo incrDepotStockReqVo = new IncrDepotStockReqVo(
                items,
                order.getOrderCode(),
                order.getDepotCode(),
                StockChangeTypeEnum.SALE,
                StockChannelEnum.NORMAL);
        stockService.updateLockedStockOnly(incrDepotStockReqVo);
    }

    /**
     * 获取促销信息
     *
     * @param orderSummaryRequestVO
     * @return
     */
    public OrderPromotionRespVo getPromotion4Order(OrderSummaryRequestVO orderSummaryRequestVO) {
        OrderPromotionReqVo orderPromotionReqVo = new OrderPromotionReqVo();
        List<OrderPromotionReqDetailVo> orderPromotionReqDetailVos = Lists.newArrayList();
        if (orderSummaryRequestVO.getStoreOrder() != null) {
            orderPromotionReqDetailVos.add(
                    OrderConvertor.orderRequestVO2PromotionReqDetailVO(
                            orderSummaryRequestVO.getStoreOrder(),
                            countTodayFinishOrder()
                    )
            );
        }
        if (orderSummaryRequestVO.getFlagshipOrder() != null) {
            orderPromotionReqDetailVos.add(
                    OrderConvertor.orderRequestVO2PromotionReqDetailVO(
                            orderSummaryRequestVO.getFlagshipOrder(),
                            countTodayFinishOrder()
                    )
            );
        }
        return promotionService.getPromotion4Order(orderPromotionReqVo);
    }

    /**
     * 获取今天完成的订单数量，已支付或货到付款的
     *
     * @return
     */
    public int countTodayFinishOrder() {
        return orderRepository.countTodayFinish(PaymentState.PAY_SUCCESS, PaymentState.PAY_ON_DELIVERY, new Timestamp(DateUtil.getTodayStartTime()));
    }

    /**
     * 查询商品详细信息
     *
     * @param orderSummaryRequestVO
     * @return
     */
    public void getProductsInfo(OrderSummaryRequestVO orderSummaryRequestVO) {
        if (orderSummaryRequestVO == null) {
            return;
        }
        DepotRespVo depot = orderSummaryRequestVO.getDepot();
        AssertRequestParameter.notNull(depot, "门店不存在");
        OrderProductReqVo orderProductReqVo = new OrderProductReqVo();
        List<String> productCodes = Lists.newArrayList();
        String depotCode = orderSummaryRequestVO.getDepotCode();
        OrderRequestVO storeOrderVO = orderSummaryRequestVO.getStoreOrder();
        if (storeOrderVO != null) {
            productCodes.addAll(this.orderItem2ProductCodes(storeOrderVO.getItems()));
        }
        OrderRequestVO flagshipOrderVO = orderSummaryRequestVO.getFlagshipOrder();
        if (flagshipOrderVO != null) {
            productCodes.addAll(this.orderItem2ProductCodes(flagshipOrderVO.getItems()));
        }
        // 组装请求视图
        orderProductReqVo.setProductCode(productCodes);
        orderProductReqVo.setDepotCode(depotCode);
        orderProductReqVo.setDepotLatitude(depot.getDepotLatitude());
        orderProductReqVo.setDepotLongitude(depot.getDepotLongitude());
        orderProductReqVo.setUserLatitude(orderSummaryRequestVO.getConsignee().getConsigneeLat());
        orderProductReqVo.setUserLongitude(orderSummaryRequestVO.getConsignee().getConsigneeLon());

        List<OrderProductInfoRespVo> orderProductInfoRespVos = productService.orderProduct(orderProductReqVo);
        // 转化成商品编号为key的HashMap
        Map<String, OrderProductInfoRespVo> productInfoRespVoMap = this.orderProductInfoRespVoList2Map(orderProductInfoRespVos);
        if (storeOrderVO != null) {
            this.settingProductInfoInOrderVO(storeOrderVO, productInfoRespVoMap);
        }
        if (flagshipOrderVO != null) {
            this.settingProductInfoInOrderVO(flagshipOrderVO, productInfoRespVoMap);
        }
    }

    /*********************************************
     * private - start                           */
    /**
     * 订单详情数组转商品编号数组
     *
     * @param orderItemVOS
     * @return
     */
    private List<String> orderItem2ProductCodes(List<OrderItemRequestVO> orderItemVOS) {
        List<String> productCodes = Lists.newArrayList();
        if (orderItemVOS != null && !orderItemVOS.isEmpty()) {
            productCodes.addAll(
                    orderItemVOS
                            .stream()
                            .map(orderItemVO -> orderItemVO.getProductCode())
                            .collect(Collectors.toList())
            );
        }
        return productCodes;
    }

    /**
     * 转化成商品编号为key的Map
     *
     * @param orderProductInfoRespVos
     * @return
     */
    private Map<String, OrderProductInfoRespVo> orderProductInfoRespVoList2Map(List<OrderProductInfoRespVo> orderProductInfoRespVos) {
        AssertUtils.notNull(orderProductInfoRespVos, OrderException.PRODUCT_INFO_NOT_FOUND);
        return orderProductInfoRespVos.stream()
                .collect(
                        Collectors.toMap(
                                o -> o.getProductBaseVo().getProductCode(),
                                o -> o
                        )
                );
    }

    /**
     * 设置商品信息到OrderVO.OrderItemVO，如果商品销售状态不符合，抛出异常
     *
     * @param orderVO
     * @param productInfoRespVoMap
     */
    private void settingProductInfoInOrderVO(OrderRequestVO orderVO, Map<String, OrderProductInfoRespVo> productInfoRespVoMap) {
        if (orderVO == null) {
            return;
        }
        if (orderVO.getItems() == null || orderVO.getItems().isEmpty()) {
            return;
        }
        if (productInfoRespVoMap == null) {
            throw new BizSilentException(OrderException.PRODUCT_INFO_NOT_FOUND);
        }
        // 门店订单
        boolean isStoreOrder = orderVO.getIsStoreOrder();
        // APP订单
        boolean isAppOrder = (orderVO.getClient() == OrderClient.android || orderVO.getClient() == OrderClient.ios);
        // 微商城订单
        boolean isWebOrder = (orderVO.getClient() == OrderClient.wechat);

        for (OrderItemRequestVO itemVO : orderVO.getItems()) {
            if (itemVO == null
                    || StringUtils.isBlank(itemVO.getProductCode())) {
                throw new BizSilentException(OrderException.PRODUCT_INFO_NOT_FOUND);
            }
            OrderProductInfoRespVo orderProductInfoRespVo = productInfoRespVoMap.get(itemVO.getProductCode());
            if (orderProductInfoRespVo == null) {
                throw new BizSilentException(OrderException.PRODUCT_INFO_NOT_FOUND);
            }
            OrderItemConvertor.productInfoRespVO2OrderItemRequestVO(
                    itemVO,
                    isStoreOrder,
                    isAppOrder,
                    isWebOrder,
                    orderProductInfoRespVo);
        }
    }
    /* private - end                              *
     **********************************************/

    /**
     * 根据门店编号获取门店的起送金额
     *
     * @param depotCode
     * @return
     */
    public Integer getDeliveryMinPriceByDepotCode(String depotCode) {
        DepotDeliverPriceRespVo vo = depotDeliverPriceService.getDepotDeliverPriceFRdb(depotCode);
        if (vo != null) {
            return vo.getPrice();
        }
        return null;
    }

    public long getNextId() {
        return idService.getNextId();
    }

    /**
     * 使用促销
     *
     * @param userId
     * @param promotionId
     * @param promotionType
     */
    public void usePromotion(Long userId, Long promotionId, PromotionTypeEnum promotionType) {
        TakeMemberPromotionReqVo takeMemberPromotionReqVo = new TakeMemberPromotionReqVo();
        takeMemberPromotionReqVo.setMemberId(userId);
        Map<Long, PromotionTypeEnum> promotions = new HashMap<>();
        promotions.put(promotionId, promotionType);
        takeMemberPromotionReqVo.setPromotions(promotions);
        promotionService.takeMemberPromotions(takeMemberPromotionReqVo);
    }

    /**
     * 保存/更新订单
     *
     * @param order
     * @return
     */
    public Order saveOrder(Order order) {
        if (order == null) {
            return null;
        }
        AssertUtils.notNull(order.getId(), OrderException.ORDER_ID_CANNOT_NULL);
        return orderRepository.save(order);
    }

    /**
     * 保存退货单
     *
     * @param returnOrder 待保存的退货单
     * @return
     */
    public ReturnOrder saveReturnOrder(ReturnOrder returnOrder) {
        if (returnOrder == null) {
            throw new BizSilentException(OrderException.RETURN_ORDER_IS_NULL);
        }
        if (returnOrder.getItems() == null || returnOrder.getItems().isEmpty()) {
            throw new BizSilentException(OrderException.RETURN_ORDER_ITEM_IS_NULL);
        }
        if (returnOrder.getId() == null) {
            returnOrder.setId(idService.getNextId());
            for (ReturnOrderItem item : returnOrder.getItems()) {
                item.setId(idService.getNextId());
            }
        }
        return returnOrderRepository.save(returnOrder);
    }

    public ReturnOrder getReturnOrderByOrderCode(String orderCode) {
        return returnOrderRepository.findByOrderCode(orderCode);
    }

    /**
     * 订单发货
     *
     * @param orderCode 订单编码
     */
    public void orderOutbound(String orderCode) {

    }

    /**
     * 根据退后单编号获取退货单
     * @param returnCode
     * @return
     */
    public ReturnOrder getreturnOrderByReturnCode(String returnCode) {
        return returnOrderRepository.findByReturnCode(returnCode);
    }
}
